#pragma once
namespace graph
{
namespace details
{
   #pragma pack(1)
   struct edge_real_t
   {
      edge_real_t(vertex_id_t target_v_id, high_way_t highway, lat_lon_t length)
         :  target_vertex_(target_v_id)
         ,  highway_(highway)
         ,  length_(length)
      {}
      vertex_id_t get_target_vertex_id() const;  
      high_way_t get_highway_tag() const;  
      lat_lon_t get_length() const;
   private:
      edge_real_t()
      {}
      vertex_id_t target_vertex_;
      high_way_t highway_;
      lat_lon_t length_;
      friend struct graph_mutable_t;
   };
   
   struct vertex_mutable_t
   {
      vertex_mutable_t(vertex_id_t id, point_t point)
         :  id_(id)
         ,  point_(point)
         ,  edges_class_(UDEFINED_KEY, UDEFINED_KEY)
      {}
      vertex_id_t get_id() const;
      point_t get_point() const;
      void set_point(point_t p);
      vertex_edge_types_t get_edge_class() const;
      void update_edge_class_inf(high_way_t tag);
      std::vector<edge_real_t> const & get_adj_edges() const;
      std::vector<edge_real_t>& get_adj_edges();
      std::vector<edge_real_t> const & get_in_adj_edges() const;
      std::vector<edge_real_t>& get_in_adj_edges();
   private:
      vertex_id_t id_;
      point_t point_;
      vertex_edge_types_t edges_class_;
      std::vector<edge_real_t> adj_edges_;
      std::vector<edge_real_t> adj_in_edges_; //edges which comes to this vertex
   };
}


struct edge_t
{
   edge_t(details::edge_real_t* real_edge, vertex_id_t source_vertex_id)
   :  real_edge_(real_edge)
   ,  source_vertex_id_(source_vertex_id)
   {}
   vertex_id_t get_target_vertex_id() const;
   vertex_id_t get_source_vertex_id() const;
   high_way_t get_highway() const;
   lat_lon_t get_length() const;
private:
   details::edge_real_t* real_edge_;
   vertex_id_t source_vertex_id_;
};

namespace details
{
    struct graph_mutable_t;
}

#pragma pack(1)
struct vertex_t
{
   vertex_t(vertex_id_t vertex_id, point_t point, vertex_edge_types_t edges_class, 
            size_t adj_list_offset, size_t adj_in_list_offset)
      :  id_(vertex_id)
      ,  point_(point)
      ,  edges_class_(edges_class)
      ,  adj_list_offset_(adj_list_offset)
      ,  adj_in_list_offset_(adj_in_list_offset)
   {}
   vertex_id_t get_id() const;
   point_t get_point() const;
   vertex_edge_types_t get_edges_types() const;
   size_t get_adj_list_offset() const;
   size_t get_adj_in_list_offset() const;
private:
   vertex_t()
   {}
   vertex_id_t id_;
   point_t point_;
   vertex_edge_types_t edges_class_;
   size_t adj_list_offset_;
   size_t adj_in_list_offset_;
   friend struct details::graph_mutable_t;
};

typedef vertex_t& vertex_ref_t;
typedef vertex_t* vertex_ptr_t;
typedef std::pair<vertex_t,vertex_t> vertex_pair_t;
typedef std::pair<vertex_id_t,vertex_id_t> vertex_id_pair_t;
}
